<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Role_model extends CI_Model{

    public function __construct() {
        parent::__construct();
    }

    /**!!!
     * Получить массив BynaryNode всех ключей для данной роли
     * @param int $role_id
     * @return array BynaryObject
     *
     */
    public function get_permissions($role_id){ //ORDER BY is_folder DESC,r_path
        $query = $this->db->query("SELECT * FROM roles_permission p inner join ".$this->config->item('resolv_table')." r on p.key_uuid = r.r_hash WHERE role_id = ? ORDER BY is_folder DESC,r_path",array($role_id));
        $permissions = array();
        foreach($query->result_array() as $row){
            $node_obj = new BinaryNode();
            $permissions[$row['R_HASH']] = $node_obj->set_by_rowdb($row);
        }
        return $permissions;
    }

    /**!!!
     * Проверка на доступ к данному Node
     * @param string $node_obj Проверяемый узел
     * @param string $perm_node узел Permisson
     * @return boolean TRUE доступ разрешен FALSE доступ запрещен
     */
    public function is_allow_node($node_obj,$perm_node){
        return (stripos($perm_node->get_path(),$node_obj->get_hash()) !== FALSE);
//        return (stripos($node_obj->get_path(),$perm_node->get_hash()) !== FALSE);
    }

    /**!!!
     * Проверка доступа к заданному узлу (СОМНИТЕЛЬНАЯ ФУНКЦИЯ)
     *
     */
    public function is_allow_node_rev($node_obj, $permissions) {
        foreach ($permissions as $perm_obj) {
            $count = substr_count($node_obj->get_path(), $perm_obj->get_hash());
            if ($count > 0) {
                return true;
                exit();
            }
        }
        return false;
    }
    
    /**!!!
     * Получить список ролей, для списков выбора админки
     * @return array
     */
    public function get_all_roles(){
        $query = $this->db->query("SELECT * FROM roles ORDER BY id");
        $roles = array();
        foreach($query->result_array() as $row){
            $roles[$row['ID']] = array("role_name"=>$row['ROLE_NAME'],"role_description"=>$row['ROLE_DESCRIPTION']);
        }
        return $roles;
    }
    
    /** !!!
     * Проверка является ли данная роль админской
     * @param int $role_id Если ID роли не указанно явно, то используется значение из $this->session->userdata['role']
     * @return boolean
     */
    public function isAdminRole($role_id = null){
        if($role_id == null){
            $role_id = $this->session->userdata('role'); 
        }
        return ($role_id == $this->config->item('admin_role_id'));
    }

    /** !!!
     * Обновление роли в БД
     * @param int $role_id
     * @param string $role_name
     * @param string $description
     * @param mixed $keys
     * @return array array("code" => 0, "msg"=>"Сообщение");
     */
    public function upd_role($role_id,$role_name,$description,$keys,$start_date,$end_date){ //,to_date(?,'DD.MM.YY'),to_date(?,'DD.MM.YY')
        $result = array("code" => 0, "msg"=>"Неопределенная ошибка");
        if($this->isAdminRole($role_id)){
            $result["msg"] = "Вы не можете изменять эту роль";
            return $result;
            exit();
        }

        if(!is_array($keys)){
            $keys = split("[;, \n]",$keys);
        }

        $this->db->query("update roles SET role_name = ?, role_description = ?, start_date_allow = to_date(?,'DD.MM.YYYY'), end_date_allow = to_date(?,'DD.MM.YYYY') WHERE id = ?",
                array(strtolower($this->db->escape_str($role_name)),$this->db->escape_str($description),$this->db->escape_str($start_date),$this->db->escape_str($end_date),(int)$role_id));
        if($keys !== FALSE && count($keys) > 0){
            $this->db->query("DELETE FROM roles_permission WHERE role_id = ?",array((int)$role_id));
            $ins = "INSERT ALL\n";
            foreach ($keys as $value) {
                if(strlen($value) > 0)
                    $ins .= "INTO roles_permission (role_id, key_uuid) VALUES (".(int)$role_id.", '".$this->db->escape_str(trim($value))."')\n";
            }
            $ins .= "SELECT * FROM dual";
            if($this->db->query($ins)){
                $result["code"] = 200;
                $result["msg"] = "Успешно добавленно записей " . $this->db->affected_rows();
            }else{
                $result["msg"] = "Ошибка добавления";
            }
        }else{
            $result['msg'] = "нет данных для записи";
        }
        return $result;
    }
    
    /*public function get_title_permissions_by_roleid($role_id){
        $perms = $this->get_permissions($role_id);
        $tree_mod = new Tree_model();
        $titles="";
        foreach ($perms as $uuid) {
            $titles .= $tree_mod->get_title_from_uuid($uuid)."\n";
        }
        return $titles;
    }*/

    /**!!!
     * Добавим новую запись роли
     * @param string $name
     * @param string $description
     * @return int affected_rows
     */
    public function add_role($name,$description){
        $this->db->query("INSERT INTO roles (role_name, role_description) VALUES (?, ?)",array(strtolower(addslashes($name)),addslashes($description)));
        return $this->db->affected_rows();
    }

    
    /**!!!
     * Return HTML of table with roles
     * @return string
     */
    public function get_roles_table(){
        $query = $this->db->query("select r.id, r.role_name, r.role_description, to_char(r.start_date_allow,'DD.MM.YYYY') START_DATE_ALLOW, to_char(r.end_date_allow,'DD.MM.YYYY') END_DATE_ALLOW, LISTAGG(p.key_uuid,';') WITHIN GROUP (ORDER BY p.rn) as key_uuid from roles r left join (select per.*, res.r_path r_path, row_number() over (ORDER BY is_folder DESC,r_path) rn from roles_permission per inner join ".$this->config->item('resolv_table')." res on per.key_uuid = res.r_hash) p on r.id = p.role_id group by r.id, r.role_name, r.role_description, r.start_date_allow, r.end_date_allow");

        $table = '<table id="role-tab" class="table table-striped table-hover table-condensed">';
        $table .= '<tr><th width="20">ID</th><th>Название</th><th>Описание</th><th>Узлы</th><th>Даты</th><th>Действия</th></tr>';
        foreach ($query->result_array() as $row){
            $permissions = $this->get_permissions($row['ID']);
            $key_str = '<ol>';
            foreach ($permissions as $perm_node) {
                $key_str .= '<li data-hash="'.$perm_node->get_hash().'">'.$perm_node->get_title_full()."</li>\n";
            }
            $key_str .= '</ol>';
            
            $str_dt = empty($row['START_DATE_ALLOW'])?"":"с ".$row['START_DATE_ALLOW'];
            $end_dt = empty($row['END_DATE_ALLOW'])?"":"до ".$row['END_DATE_ALLOW'];
            $str_br = (!empty($str_dt) && !empty($end_dt))?"<br>":" ";
            $date_var = trim($str_dt . $str_br . $end_dt);
            
//            $descript = $row['ROLE_DESCRIPTION'] . (empty($date_var)?"":"<br><i>[".$date_var."]</i>");
            $table .= sprintf('<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td class="text-nowrap" data-startdate="%s" data-enddate="%s"><em>%s</em></td>'
                    . '<td width="50" data-roleid="%d"><span class="badge alert-warning glyphicon glyphicon-pencil hand has-tooltip" title="Редактировать" data-toggle="modal" data-target="#modalEditRole"> </span> '
                    . '<span class="badge alert-danger glyphicon glyphicon-remove hand has-tooltip" data-toggle="modal" title="Удалить" data-target="#modalDelRole"> </span></td></tr>',
                        $row['ID'],$row['ROLE_NAME'],$row['ROLE_DESCRIPTION'],$key_str,$row['START_DATE_ALLOW'],$row['END_DATE_ALLOW'],$date_var,$row['ID']);
        }
        $table .= '</table>';
        return $table;
    }

    /**
     *Проверка доступа к заданному узлу
     *@deprecated since version 2
     */
    public function access_for_chart($chart_path,$permissions_array){
        foreach ($permissions_array as $value) {
            $count = substr_count($chart_path, $value);
            if($count > 0 ){
                return true;
                exit();
            }
        }
        return false;
    }
    
    /**
     * Почистить мусор
     * @param type $id_role
     */
    public function clear_up_trash($roleid){
        $affect = 0;
        $query_bookmark = "delete from bookmarks where bookmarks.id IN (
            with A as (
            select bk.id, bk.user_id, bk.type, bk.parent_id p_id, rs.*  from bookmarks bk, ".$this->config->item('resolv_table')." rs
            where 1=1 and bk.type_id = rs.r_id and bk.user_id IN (
                select users.id from users inner join roles_users on users.id = roles_users.user_id inner join roles on roles_users.role_id = roles.id where roles.id = ?
            )),
            B as (select '%' || T.KEY_UUID || '%' uuid from roles_permission T where role_id = ?)
            select A.id from A where not exists (select 1 from B where A.R_Path like B.uuid))";
        $this->db->query($query_bookmark,array((int)$roleid,(int)$roleid));
        $affect += $this->db->affected_rows();

        $query_u_menu = "delete from user_menu
            where user_id IN (
                select users.id from users inner join roles_users on users.id = roles_users.user_id inner join roles on roles_users.role_id = roles.id
                where roles.id = ?
            )";
        $this->db->query($query_u_menu,array((int)$roleid));
        $affect += $this->db->affected_rows();

        return $affect;
    }

    public function delete_role($roleid){
        $this->db->query("delete from roles where id = ? ",array((int)$roleid));
        return $this->db->affected_rows();
    }
    
    
    /** new func v2 ******************************** */

    /**!!!
     * 
     * @param string $cur_date String time in format 'j.m.y'
     * @return boolean
     */
    public function access_chart_by_date($cur_date) {
        try {
            $st_date = ($this->session->userdata('start_date'))? new DateTime($this->session->userdata('start_date')) : FALSE;
            $en_date = ($this->session->userdata('end_date'))  ? new DateTime($this->session->userdata('end_date'))   : FALSE;
            //$cur_date = date_create_from_format('j.m.y', $cur_date);
            $cur_date =  new DateTime($cur_date);
//            var_dump($cur_date->format('Y-m-d H:i:s'));
        } catch (Exception $e) {
            echo $e->getMessage();
            return FALSE;
            //exit(1);
        }
        if($st_date === FALSE && $en_date === FALSE){
            return TRUE;
        }elseif($st_date !== FALSE && $en_date !== FALSE){
            return ($st_date <= $cur_date && $cur_date <= $en_date);
        }elseif($st_date !== FALSE){
            return $st_date <= $cur_date;
        }elseif($en_date !== FALSE){
            return $cur_date <= $en_date;
        }
    }
    
}
